package top.dark.controller;

import com.alibaba.fastjson.TypeReference;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import top.dark.feign.MemberFeignService;
import top.dark.vo.UserLoginVo;
import top.dark.vo.UserRegisterVo;
import top.dark.common.constant.AuthConstant;
import top.dark.common.exception.BizCodeEnum;
import top.dark.common.utils.R;
import top.dark.feign.ThirdPartyFeignService;
import javax.validation.Valid;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * Author: lijiao
 * description:
 * Create Time: 2021/3/20 12:49
 */
@Slf4j
@Controller
public class IndexController {

   /* @RequestMapping("/register.html")
    public String register(){
        return "register";
    }

    @RequestMapping(value = {"/login.html","/"})
    public String login(){
        return "login";
    }
*/
    @Autowired
    ThirdPartyFeignService thirdPartyFeignService;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private MemberFeignService memberFeignService;

    @ResponseBody
    @RequestMapping("/sms/sendCode")
    public R sendCode(@RequestParam("msisdn") String msisdn) {
        // TODO 接口防刷
        String value = redisTemplate.opsForValue().get(AuthConstant.SMS_CODE_CACHE_PREFIX + msisdn);
        if (StringUtils.isNotEmpty(value)) {
            String[] str = value.split("_");
            // 60秒内防止在次下发短信
            if (System.currentTimeMillis() - Long.parseLong(str[1]) < 60000){
                return R.error(BizCodeEnum.SMS_CODE_EXCEPTION.getCode(), BizCodeEnum.SMS_CODE_EXCEPTION.getMsg());
            }
        }
        String code = UUID.randomUUID().toString().substring(0, 6).toUpperCase();
        String redisValue = code + "_" + System.currentTimeMillis();
        redisTemplate.opsForValue().
                set(AuthConstant.SMS_CODE_CACHE_PREFIX + msisdn, redisValue, 5, TimeUnit.MINUTES);
        // 下发短信验证码
        R r = thirdPartyFeignService.sendSmsCode(msisdn, code + ",5");
        if (r == null) {
           return R.error(BizCodeEnum.SMS_FAIL_EXCEPTION.getCode(),
                    BizCodeEnum.SMS_FAIL_EXCEPTION.getMsg());
        }
        return r;
    }

    /**
     * RedirectAttributes redirect : 模拟重定向携带数据
     * TODO 重定向携带数据原理
     *  利用session原理，将数据放在session中，只要跳转到下一个页面取出这个数据以后，session里面的数据就会被删掉
     * TODO 分布式下的session问题
     */
    @RequestMapping("/register")
    public String register(@Valid UserRegisterVo vo, BindingResult result, RedirectAttributes redirect) {
        if (result.hasErrors()) {
            Map<String, String> errors = new HashMap<>();
            result.getFieldErrors().stream().forEach(fieldError -> {
                errors.put(fieldError.getField(), fieldError.getDefaultMessage());
            });
            redirect.addFlashAttribute("errors", errors);
            // 如果校验失败，重定向到注册页面（避免重复提交）
            return "redirect:http://auth.gulimall.com/register.html";
        }

        // 校验验证码
        String smsCode = vo.getSmsCode();
        String code = redisTemplate.opsForValue().get(AuthConstant.SMS_CODE_CACHE_PREFIX + vo.getPhone());
        int flag = 0;
        R<String> register = R.error(BizCodeEnum.REMOTE_CALL_EXCEPTION.getCode(), BizCodeEnum.REMOTE_CALL_EXCEPTION.getMsg());
        if (StringUtils.isNotEmpty(code)) {
            String[] str = code.split("_");
            if (str[0].equalsIgnoreCase(smsCode)) {
                // 删除验证码；令牌机制
                redisTemplate.delete(AuthConstant.SMS_CODE_CACHE_PREFIX + vo.getPhone());
                // 真正注册需要调用远程服务进行注册
                try {
                    register = memberFeignService.register(vo);
                    if (register != null && register.getCode() == 0) {
                        // 注册成功
                        flag = 1;
                    } else {
                        flag = 2;
                    }
                } catch (Exception e) {
                    flag = 2;
                    log.error("远程调用会员服务注册账号异常，异常信息：{}", e);
                }

            }
        }

        if (flag == 0) {
            // 验证码校验失败跳转
            Map<String, String> errors = new HashMap<>();
            errors.put("smsCode","验证码错误");
            redirect.addFlashAttribute("errors", errors);
            // 如果校验失败，重定向到注册页面（避免重复提交）
            return "redirect:http://auth.gulimall.com/register.html";
        } else if (flag == 2) {
            // 远程调用会员服务注册会员失败
            Map<String, String> errors = new HashMap<>();
            errors.put("msg",register.getData("msg", new TypeReference<String>() {}));
            redirect.addFlashAttribute("errors", errors);
            // 如果校验失败，重定向到注册页面（避免重复提交）
            return "redirect:http://auth.gulimall.com/register.html";
        }

        // 注册成功回到首页，跳转到登录页
        return "redirect:http://auth.gulimall.com/login.html";
    }

    @RequestMapping("/login")
    public String login(@Valid UserLoginVo vo,BindingResult result,RedirectAttributes redirect){
        if (result.hasErrors()) {
            Map<String, String> errors = new HashMap<>();
            result.getFieldErrors().stream().forEach(fieldError -> {
                errors.put(fieldError.getField(), fieldError.getDefaultMessage());
            });
            redirect.addFlashAttribute("errors", errors);
            return "redirect:http://auth.gulimall.com/login.html";
        }

        // 调用会员服务校验登录
        Map<String, String> errors = new HashMap<>();
        try {
            R login = memberFeignService.login(vo);
            if (login != null && login.getCode() == 0) {
                // TODO 登录成功后的处理
                return "redirect:http://gulimall.com/";
            }
            errors.put("msg", BizCodeEnum.LOGIN_PASS_ERROR_EXCEPTION.getMsg());
        } catch (Exception e) {
            log.info("远程调用会员服务登录异常，异常信息：{}", e);
            errors.put("msg", BizCodeEnum.REMOTE_CALL_EXCEPTION.getMsg());
        }
        redirect.addFlashAttribute("errors", errors);
        return "redirect:http://auth.gulimall.com/login.html";
    }
}
